<template>
  <div class="vui-widget vui-scroll" :style="{width:width + 'px' ,height: height + 'px'}" :class="{'vui-scroll-scrolling':isScrolling,'vui-scroll-light':theme == 'light',vclass}" ref="container" @mousewheel="onMouseWheel($event)">
      <div ref="content" class="ui-scroll-content" :style="{'margin-left':contentLeft + 'px','margin-top':contentTop + 'px'}">
        <slot></slot>
      </div>   
      <div ref="leftbar" v-if="contentWidth > containerWidth" @mousedown.stop="onMouseDown($event,'left')" :style="{'width':barWidth + 'px','left':scrollLeft + 'px'}" class="vui-scroll-bar vui-scroll-bar-horizontal" :class="{'vui-scroll-bar-light':theme == 'light'}"></div>   
      <div ref="topbar" v-if="contentHeight > containerHeight" @mousedown.stop="onMouseDown($event,'top')" :style="{'height':barHeight + 'px','top':scrollTop + 'px'}" class="vui-scroll-bar vui-scroll-bar-vertical" :class="{'vui-scroll-bar-light':theme == 'light'}"></div>    
  </div>
</template>

<script>
import {DomHandler} from '../common/domhandler';
import {Event} from '../event/event';
export default {
  props:{
    width: Number,
    height: Number,
    theme: {
      type: String,
      default: 'dark'
    },
    vclass: String
  },
  data () {
    return {
      container: null,
      content: null,
      leftBar: null,
      topBar: null,
      containerWidth: 0,
      containerHeight: 0,
      contentWidth: 0,
      contentHeight: 0,
      wheelStep:0,
      oldSizerecorder: '',
      sizeRecorder: '',
      scrollTop: 0,
      scrollLeft: 0,
      scrollingLeft: 0,
      scrollingTop: 0,
      contentLeft: 0,
      contentTop: 0,
      startTop: 0,
      startLeft:0,
      isScrolling:false,
      activeDirection:null,
      scrollTimer: null,
    }
  },

  computed:{
    barWidth:function(){
      return ((this.containerWidth / this.contentWidth * this.containerWidth < 20)?20:(this.containerWidth / this.contentWidth * this.containerWidth));
    },
    barHeight:function(){
      return ((this.containerHeight / this.contentHeight * this.containerHeight < 20)?20:(this.containerHeight / this.contentHeight * this.containerHeight));
    }
  },
  created:function(){
    this.$nextTick(() => {
      this.container = this.$refs.container;
      this.content = this.$refs.content;
      this.leftBar = this.$refs.leftbar;
      this.topBar = this.$refs.topbar;
      this.updateSize();
      this.updateScrollBar();
      document.body.addEventListener('mousemove',this.updateSize);
    });
  },

  updated: function(){
    if(!this.container || !this.content) return;
    this.updateSize();
    if(this.containerWidth >= this.contentWidth){
      this.contentLeft = 0;
    }
    if(this.containerHeight >= this.contentHeight){
      this.contentTop = 0;
    }
    if(this.oldSizerecorder != this.sizeRecorder){
      this.oldSizerecorder = this.sizeRecorder;
      this.updateScrollBar();
    }
    this.wheelStep = this.containerHeight;
    Event.$emit('vupdate');
  },

  destoryed: function(){
    this.destoryMouseListener();
    document.body.removeEventListener('mouseleave',this.destoryMouseListener);
  },

  methods: {
    onMouseDown(event,direction){
      this.activeDirection = direction || 'top';
      this.isScrolling = true;
      this.startLeft = event.clientX;
      this.startTop = event.clientY;
      this.scrollingLeft = this.scrollLeft;
      this.scrollingTop = this.scrollTop;
      document.body.classList.add('unselect');
      document.body.addEventListener('mousemove',this.onMouseMove);
      document.body.addEventListener('mouseup',this.onMouseUp);
      document.body.addEventListener('mouseleave',this.destoryMouseListener);
    },

    onMouseMove(event){
      // 根据当前鼠标位置判断是否已经滑出可触发滚动的范围
      if(this.activeDirection == 'left'){
        if(Math.abs(event.clientY - this.startTop) > 100){
          this.destoryMouseListener();
          return false;
        }
      } else {
        if(Math.abs(event.clientX - this.startLeft) > 100){
          this.destoryMouseListener();
          return false;
        }
      }
      this.updateContentPosition(event);
      this.$emit('onScrollEnd',{containerWidth:this.containerWidth,containerHeight:this.containerHeight,contentWidth:this.contentWidth,contentHeight:this.contentHeight,scrollLeft:this.scrollLeft,scrollTop:this.scrollTop});
    },

    onMouseUp(event){
      this.activeDirection = null;
      this.destoryMouseListener();
    },

    onMouseWheel(event){
      if(this.contentHeight <= this.containerHeight) return;
      this.activeDirection = 'top';
      this.isScrolling = true;

      event.stopPropagation();
      let direction = -Math.abs(event.wheelDelta) / event.wheelDelta;
      let wheelDelta = direction * this.wheelStep * (this.containerHeight - this.barHeight) / (this.contentHeight - this.containerHeight);
      this.scrollTop = (this.scrollTop + wheelDelta < 0)?0:(this.scrollTop + wheelDelta > this.containerHeight - this.barHeight?(this.containerHeight - this.barHeight):(this.scrollTop + wheelDelta));
      this.contentTop = -(this.scrollTop * (this.contentHeight - this.containerHeight) / (this.containerHeight - this.barHeight));
      this.activeDirection = null;
      
      this.$emit('onScrolling',{containerWidth:this.containerWidth,containerHeight:this.containerHeight,contentWidth:this.contentWidth,contentHeight:this.contentHeight,scrollLeft:this.scrollLeft,scrollTop:this.scrollTop});
      if(this.scrollTimer){
        clearTimeout(this.scrollTimer);
        this.scrollTimer = null;
      }
      this.scrollTimer = setTimeout(() => {
        this.isScrolling = false;
      },200);
    },

    updateContentPosition(event){
      let moveTop = event.clientY;
      let moveLeft = event.clientX;
      if(this.activeDirection == 'left'){
        let scrollLeft = (this.scrollingLeft + moveLeft - this.startLeft < 0)?0:((this.scrollingLeft + moveLeft - this.startLeft > this.containerWidth - this.barWidth)?(this.containerWidth - this.barWidth):this.scrollingLeft + moveLeft - this.startLeft);
        this.contentLeft = -(scrollLeft * (this.contentWidth - this.containerWidth) / (this.containerWidth - this.barWidth));
      } else {
        let scrollTop = (this.scrollingTop + moveTop - this.startTop < 0)?0:((this.scrollingTop + moveTop - this.startTop > this.containerHeight - this.barHeight)?(this.containerHeight - this.barHeight):this.scrollingTop + moveTop - this.startTop);
        this.contentTop = -(scrollTop * (this.contentHeight - this.containerHeight) / (this.containerHeight - this.barHeight));
      }
      this.updateScrollBar();
    },

    updateScrollBar(){
      if(!this.container || !this.content ) return;
      let scrollLeft = -this.contentLeft / this.contentWidth * this.containerWidth;
      let scrollTop = -this.contentTop / this.contentHeight * this.containerHeight;
      this.scrollLeft = scrollLeft < 0?0:(scrollLeft > this.containerWidth - this.barWidth?this.containerWidth - this.barWidth:scrollLeft);
      this.scrollTop = scrollTop < 0?0:(scrollTop > this.containerHeight - this.barHeight?this.containerHeight - this.barHeight:scrollTop);
    },

    updateSize(){
      this.containerWidth = DomHandler.getInnerWidth(this.container);
      this.containerHeight = DomHandler.getInnerHeight(this.container);
      this.contentWidth = DomHandler.getInnerWidth(this.content);
      this.contentHeight = DomHandler.getInnerHeight(this.content);
      this.sizeRecorder = this.containerWidth + ',' + this.containerHeight + ',' + this.contentWidth + ',' + this.contentHeight;
    },

    destoryMouseListener(){
      document.body.removeEventListener('mousemove',this.onMouseMove);
      document.body.removeEventListener('mouseup',this.onMouseUp);
      document.body.removeEventListener('mousemove',this.updateSize);
      document.body.classList.remove('unselect');
      this.isScrolling = false;
      this.$emit('onScrollEnd',{containerWidth:this.containerWidth,containerHeight:this.containerHeight,contentWidth:this.contentWidth,contentHeight:this.contentHeight,scrollLeft:this.scrollLeft,scrollTop:this.scrollTop});
    },
  }
}
</script>